<template>
  <a-form ref="formRef" :model="formModel" v-bind="formConfig" auto-label-width>
    <a-row :gutter="24">
      <a-col v-for="item in props.formItems" v-bind="item.col">
        <BaseFormItem :form-item="item" />
      </a-col>
    </a-row>
  </a-form>
</template>

<script setup lang="ts">
import { FieldData } from "@arco-design/web-vue/es/form/interface";
import {
  FormItem,
  FormMethods,
  FormRegister,
  FormValidateCallback,
  FormValidateReturn,
} from "./types";
import { isArray, isObject, merge, set } from "lodash-es";
import { FORM_MODEL_KEY } from "./config";
import BaseFormItem from "./component/BaseFormItem.vue";

const props = defineProps<{
  formKey: InjectionKey<FormRegister>;
  formItems: FormItem[];
}>();
const formRef = ref<Nullable<FormMethods>>(null);
const formModel = ref<Record<string, any>>({});
const formConfig = ref({});
const register = inject(props.formKey);

const validate = (callback?: FormValidateCallback) => {
  return formRef.value?.validate(callback) as FormValidateReturn;
};
const validateField = (field: string | string[], callback: FormValidateCallback) => {
  return formRef.value?.validateField(field, callback) as FormValidateReturn;
};
const resetField = (field: string | string[]) => {
  formRef.value?.resetField(field);
};
const clearValidate = (field: string | string[]) => {
  formRef.value?.clearValidate(field);
};
const setFields = (data: Record<string, FieldData>) => {
  formRef.value?.setFields(data);
};
const scrollToField = (field: string) => {
  formRef.value?.scrollToField(field);
};
const getFormValue = () => {
  return unref(formModel);
};
const setFormValue = (model?: Record<string, any>) => {
  if (model) {
    Object.assign(formModel.value, model);
  } else {
    formModel.value = {};
  }
};

const _updateFormItem = (formItem: FormItem) => {
  const field = formItem.field;
  if (!field) return;
  props.formItems.forEach((item) => {
    if (!item.onlyItem) {
      if (item.field == field) {
        merge(item, formItem);
      }
    } else if (item.content) {
      item.content.forEach((contentItem) => {
        if (contentItem.field == field) {
          merge(contentItem, formItem);
        }
      });
    }
  });
};

const updateFormItem = (formItemConfig: FormItem | FormItem[]) => {
  if (isArray(formItemConfig)) {
    formItemConfig.forEach((formItem) => _updateFormItem(formItem));
  } else if (isObject(formItemConfig)) _updateFormItem(formItemConfig);
};

// const initModelDefaultValue = () => {
//   formItems.value.forEach((item) => {
//     const defaultValue = (item.props as any)?.defaultValue;
//     if (defaultValue) set(formModel.value, item.field, defaultValue);
//   });
// };

// const setFormItem = (items: FormItem[]) => {
//   formItems.value = items;
//   initModelDefaultValue();
// };

const setFormConfig = (config?: any) => {
  formConfig.value = config ?? {};
};

provide(FORM_MODEL_KEY, formModel);

onMounted(() => {
  props.formItems.forEach((item) => {
    const defaultValue = (item.props as any)?.defaultValue;
    if (defaultValue) set(formModel.value, item.field, defaultValue);
  });
  register?.({
    validate,
    validateField,
    resetField,
    clearValidate,
    setFields,
    scrollToField,
    getFormValue,
    setFormValue,
    setFormConfig,
    updateFormItem,
  });
});
</script>
